import re
import time
import Page
import allure
import logging
import requests
import telnetlib

"""TelnetClient类封装查看设备参数方法，给测试脚本断言使用"""


class TelnetClient():

    def __init__(self, ):
        # 实例化
        self.tn = telnetlib.Telnet()

    # 获取开通telnet所需密码
    @allure.step(title="获取开通telnet所需密码")
    def get_pwd(self, device_ip):
        for i in Page.devices_ip:
            if device_ip == i.get("device_ip"):
                print(i.get("device_ip"))
                print(i.get("pwd"))
                print(i.get("auth"))
                return i.get("pwd"), i.get("auth")

    # 通过API开通设备telnet
    @allure.step(title="API开通设备telnet")
    def open_telnet(self, device_ip):
        device_text = self.get_pwd(device_ip)
        headers = {

            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36',
            'Connection': 'keep-alive',
            'Authorization': device_text[1],
        }
        session = requests.session()

        data = {
            'username': 'Lucky787',
            'password': device_text[0],
        }
        try:
            url = "http://{}:787".format(device_ip)
            r = session.post(url=url, data=data, headers=headers)
        except:
            allure.attach("失败描述", "%s开通telnet失败" % device_ip)
            return False

    # 此函数实现telnet登录主机
    @allure.step(title="telnet登录主机")
    def login_host(self, device_ip, username, password):
        try:
            # 开通telnet
            self.open_telnet(device_ip)
            # self.tn = telnetlib.Telnet(host_ip,port=23)
            time.sleep(5)
            self.tn.open(device_ip, port=23)
        except:
            allure.attach("失败描述", '%s网络连接失败' % device_ip)
            return False
        # 等待login出现后输入用户名，最多等待10秒
        self.tn.read_until(b'login: ', timeout=10)
        self.tn.write(username.encode('ascii') + b'\n')
        # 等待Password出现后输入用户名，最多等待10秒
        self.tn.read_until(b'Password: ', timeout=10)
        self.tn.write(password.encode('ascii') + b'\n')
        # 延时两秒再收取返回结果，给服务端足够响应时间
        time.sleep(2)
        # 获取登录结果
        # read_very_eager()获取到的是的是上次获取之后本次获取之前的所有输出
        command_result = self.tn.read_very_eager().decode('ascii')
        if 'Login incorrect' not in command_result:
            logging.warning('%s登录成功' % device_ip)
            return True
        else:
            logging.warning('%s登录失败，用户名或密码错误' % device_ip)
            return False

    # 此函数实现执行传过来的命令，并输出其执行结果
    @allure.step(title="输出其执行结果")
    def execute_some_command(self, command):
        # 执行命令
        self.tn.write(command.encode('ascii') + b'\n')
        time.sleep(2)
        # 获取命令结果
        # command_result = self.tn.read_very_eager().decode('ascii')
        command_result = self.tn.read_very_eager().decode('utf-8')
        # logging.warning('命令执行结果：\n%s' % command_result)
        return command_result

    # 退出telnet
    def logout_host(self):
        self.tn.write(b"exit\n")

    # 取出value
    def take_v(self, slotList):
        v = []
        for i in slotList[0].split(','):
            v.append(i)
        # print(v)
        value = v[1][8:]
        # print(value)
        return value

    # telnet返回参数转换(抓拍阈值)
    def param_trans_frontthr(self, value):
        if value == -2000:
            return 1
        if value == -1000:
            return 2
        if value == 0:
            return 3
        if value == 500:
            return 4
        if value == 1000:
            return 5
        if value == 1200:
            return 6
        if value == 1400:
            return 7
        if value == 1600:
            return 8
        if value == 1700:
            return 9
        if value == 1800:
            return 10

    # telnet返回参数转换(时间有关)
    def param_trans_time(self, value):
        if value == 10:
            return 0.5
        if value == 25:
            return 1
        if value == 50:
            return 2
        if value == 75:
            return 3
        if value == 100:
            return 4
        if value == 125:
            return 5
        if value == 250:
            return 10
        if value == 500:
            return 20
        if value == 750:
            return 30
        if value == 1000:
            return 40

    # telnet返回参数转换
    def param_trans(self, value):
        if value == 70:
            return 1
        if value == 66:
            return 2
        if value == 64:
            return 3
        if value == 63:
            return 4
        if value == 62:
            return 5
        if value == 61:
            return 6
        if value == 60:
            return 7
        if value == 59:
            return 8
        if value == 58:
            return 9
        if value == 57:
            return 10

    @allure.step(title="登录telnet,取出设备参数")
    def login_telnet(self, device_ip='10.64.31.58'):
        try:
            host_ip = device_ip
            username = 'root'
            password = 'antslq'
            command = 'pwd'
            telnet_client = TelnetClient()
            # 如果登录结果返加True，则执行命令，然后退出
            if telnet_client.login_host(host_ip, username, password):
                telnet_client.execute_some_command(command)
                ret = telnet_client.execute_some_command('cat /param/sunrise_smart.conf')
                # 退出登录
                telnet_client.logout_host()
                return ret
        except Exception as e:
            allure.attach("错误说明", "登录telnet,取出设备参数失败,原因:{}".format(e))
            raise Exception("登录telnet,取出设备参数失败")

    """
    返回IPC参数的值,返回的是字符串,【调参断言使用】
    1.track_score_eliminate -----灵敏度
    2.beginpostframethr-----目标抓拍时间
    3.resnapthr-----再次抓取时间差
    4.firstnumavailthr-----抓拍图片数
    5.frontthr-----抓拍阈值
    6.snapscale-----人脸外扩系数
    7.snapsizethr-----抓拍最小人脸尺寸
    """

    # 获取telnet调参参数 【调参断言使用】list
    @allure.step(title="telnet连接IPC取出参数")
    def telnet_ipc_param(self, device_ip='10.64.31.58'):
        try:
            ret = self.login_telnet(device_ip)
            # 用于存放所有参数
            telnet_params = []
            # 遍历7个参数的值
            for i in range(0, 7):
                if i == 0:
                    # 取出灵敏度相关的值
                    rule = r'track_score_eliminate(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = int(self.take_v(slotList))
                    # 转换取出的值与页面值统一
                    param = self.param_trans(value)
                    # 将灵敏度放入指定变量
                    telnet_params.append(param)
                if i == 1:
                    # 取出目标抓拍时间相关的值
                    rule = r'beginpostframethr(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = int(self.take_v(slotList))
                    # 转换取出的值与页面值统一
                    param = self.param_trans_time(value)
                    # 将目标抓拍时间放入指定变量
                    telnet_params.append(param)
                if i == 2:
                    # 取出抓拍图片数
                    rule = r'firstnumavailthr(.*?)}'
                    slotList = re.findall(rule, ret)
                    # print(slotList)
                    value = int(self.take_v(slotList))
                    # 将抓拍图片数放入指定变量
                    telnet_params.append(value)
                if i == 3:
                    # 取出抓拍阈值相关的值
                    rule = r'frontthr(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = int(self.take_v(slotList))
                    # 转换取出的值与页面值统一
                    param = self.param_trans_frontthr(value)
                    # 将灵敏度放入指定变量
                    telnet_params.append(param)
                if i == 4:
                    # 取出人脸外扩系数
                    rule = r'snapscale(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = float(self.take_v(slotList))
                    # 将抓人脸外扩系数放入指定变量
                    telnet_params.append("%.1f" % value)
                if i == 5:
                    # 取出抓拍最小人脸尺寸
                    rule = r'snapsizethr(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = int(self.take_v(slotList))
                    # 将抓人脸外扩系数放入指定变量
                    telnet_params.append(value)
                if i == 6:
                    # 取出再次抓取时间差
                    rule = r'resnapthr(.*?)}'
                    slotList = re.findall(rule, ret)
                    value = int(self.take_v(slotList))
                    if value == None or value =="":
                        pass
                    else:
                        # 转换取出的值与页面值统一
                        param = self.param_trans_time(value)
                        # 将目标抓拍时间放入指定变量
                        telnet_params.append(param)
            allure.attach("描述", "telnet参数：灵/目标/图片/阈值/人脸尺寸/系数/时间差:[{}]".format(telnet_params))
            return telnet_params
        except Exception as e:
            allure.attach("描述", "try的telnet连接IPC取出参数失败,原因：{}".format(e))

    # 获取telnet中space_id 【设备空间断言使用】str
    @allure.step(title="获取telnet中space_id")
    def telnet_ipc_space(self, device_ip='10.64.31.58'):
        try:
            # telnet登录
            ret = self.login_telnet(device_ip)
            # 处理数据
            rule = r'leveltwo_id(.*?)}'
            slotList = re.findall(rule, ret)
            value = self.take_v(slotList)
            if value == None or value == "":
                allure.attach("描述", "if的telnet此设备无space_id")
                return ""
            else:
                value = value[1:]
                # 返回telnet中取出的space_id
                allure.attach("描述", "telnet中取出的space_id:[{}]".format(value[:-1]))
                return value[:-1]
        except TypeError as e:
            allure.attach("描述", "try的telnet连接IPC取出space_id失败,原因：[{}]".format(e))
            return ""


if __name__ == '__main__':
    p = TelnetClient()
    # 测试
    print(p.telnet_ipc_param("10.64.31.58"))
    # print(p.telnet_ipc_space())
